#pragma once

#include <Shlobj.h>
#include <string>
#include <AtlBase.h>
#include <AtlConv.h>
#include "../../common/Interfaces/IEnvironment.h"


class k_Environment : public IEnvironment
{
public:
	k_Environment()
		: mh_Instance(0)
	{
	}

	k_Environment(HINSTANCE ah_Instance)
	{
		this->set_Module(ah_Instance);
	}

	// IObject
	void* QueryInterface(const GUID& ar_InterfaceGuid)
	{
		if (ar_InterfaceGuid == __uuidof(IEnvironment)) 
		return static_cast<IEnvironment*>(this);
		else if (ar_InterfaceGuid == __uuidof(IService)) 
			return static_cast<IService*>(this);

		return NULL; 
	}

	// IService
	virtual void Initialize(IServiceLocator& ar_ServiceLocator)
	{
	}

	virtual void Deinitialize()
	{
	}

	virtual bool get_IsInitialized() const
	{
		return mh_Instance != NULL;
	}
	
	// IEnvironment
	virtual void set_Module(HINSTANCE ah_Instance)
	{
		mh_Instance = ah_Instance;
		wchar_t szPath[MAX_PATH];
		if(0 != GetModuleFileNameW( NULL, szPath, MAX_PATH ) )
		{
			ms_ModuleFileName = szPath;
			size_t li_Position = ms_ModuleFileName.rfind(L"\\");
			if (li_Position != std::wstring::npos)
			{
				ms_ModulePath = ms_ModuleFileName;
				ms_ModulePath.resize(li_Position+1);
				ms_ModuleFileName.erase(ms_ModuleFileName.begin(), ms_ModuleFileName.begin() + li_Position + 1);
			}
		}

		::GetCurrentDirectoryW(MAX_PATH, szPath);
		ms_WorkPath = szPath;
		ms_WorkPath += L"\\";
		ms_WalhallPath = ms_WorkPath;

		HKEY lh_OpenedKey;
		if (::RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Walhall\\Walhall", 0, KEY_READ, &lh_OpenedKey) == S_OK)
		{
			DWORD ldw_DataLength = MAX_PATH;
			BYTE lc_Data[MAX_PATH] = "";
			::RegQueryValueExA(lh_OpenedKey, "WalhallPath", 0, 0, lc_Data, &ldw_DataLength);
			::RegCloseKey(lh_OpenedKey);

			std::string ls_PathA = (char*)lc_Data;
			USES_CONVERSION;
			ms_WalhallPath = A2W(ls_PathA.c_str());
		}

		IMalloc* lr_ShellMalloc_;
		LPITEMIDLIST lh_Pidl;

		HRESULT hres = SHGetMalloc(&lr_ShellMalloc_);
		if (::SHGetSpecialFolderLocation(NULL, CSIDL_APPDATA, &lh_Pidl) == NOERROR)
		{
			wchar_t ls_Buffer[MAX_PATH];
			::SHGetPathFromIDListW(lh_Pidl, ls_Buffer);
			ms_AppDataDirectory = ls_Buffer;
			ms_AppDataDirectory += L"\\";
			lr_ShellMalloc_->Free(lh_Pidl);
		}

		lr_ShellMalloc_->Release();
	}

	virtual HINSTANCE get_Module() const  {return mh_Instance;}
	virtual std::wstring get_ModuleFilename() const {return ms_ModuleFileName;}
	virtual std::wstring get_ModulePath() const {return ms_ModulePath;}
	virtual std::wstring get_WorkPath() const {return ms_WorkPath;}
	virtual std::wstring get_WalhallPath() const {return ms_WalhallPath;}
	virtual std::wstring get_AppDataDirectory() const {return ms_AppDataDirectory;}

private:
	HINSTANCE mh_Instance;
	std::wstring ms_ModuleFileName;
	std::wstring ms_ModulePath;
	std::wstring ms_WorkPath;
	std::wstring ms_WalhallPath;
	std::wstring ms_AppDataDirectory;
};
